﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SIGEB.Prototipo.Control;
using SIGEB.Modelo.moduloPerfiles;
using SIGEB.Modelo;

namespace SIGEB.Prototipo.Vista.moduloPerfiles
{
    public partial class frm_TipoPerfil : frm_IMEC
    {
        #region "constructores"

        public frm_TipoPerfil()
        {
            InitializeComponent();
        }

        public frm_TipoPerfil(controlPrincipal cp)
            : base(cp)
        {
            InitializeComponent();
            estado = new estadoVentanaImec();
            datosActuales = new LinkedList<tipoPerfil>();
            estado.consultar();
            iniciaArbol();
            asignarUI(this.Controls);
            try
            {
                datosActuales = cp.ctrlTipoPerfil.obtenerTiposPerfil();
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }
            llenarListaTiposPerfil(datosActuales);
            actualizaControles();
            base.dgv_busqueda = dgv_BusquedaPerfiles;
        }

        #endregion

        #region "métodos"

        /// <summary>
        /// prepara el arbol para que pueda ser utilizado
        /// </summary>
        private void iniciaArbol()
        {
            arbol = new manejaArbol();
            arbol.agregaSelectAll(checkBox65);
            arbol.agregarHijos(cbx_computadoras1, new CheckBox[] { cbx_PC1 });
            arbol.agregarHijos(cbx_documentos2, new CheckBox[] { doc1, doc2, doc3, doc4 });
            arbol.agregarHijos(cbx_tipoPerfil4, new CheckBox[] { tiperf1, tiperf2, tiperf3, tiperf4 });
            arbol.agregarHijos(cbx_usr5, new CheckBox[] { usr1, usr2, usr3, usr4, usr5, usr6, perf3, perf4, perf5, grps4, grps6 });
            arbol.agregarHijos(cbx_tipusr6, new CheckBox[] { tipusr1, tipusr2, tipusr3, tipusr4 });
            arbol.agregarHijos(cbx_grps7, new CheckBox[] { grps1, grps2, grps3, grps5 });
            arbol.agregarHijos(cbx_notif8, new CheckBox[] { notif1 });
            arbol.agregarHijos(cbx_mult9, new CheckBox[] { mult1, mult2, mult3, mult4 });
            arbol.agregarHijos(cbx_prest10, new CheckBox[] { prest1, prest2, prest3, prest4, prest5, prest6 });
            arbol.agregarHijos(cbx_res11, new CheckBox[] { res1, res2, res3, res4, res5, res6, res7 });
            arbol.agregarHijos(cbx_cons12, new CheckBox[] { cons1 });
            arbol.agregarHijos(cbx_est13, new CheckBox[] { est1, est2 });
            arbol.agregarHijos(cbx_tipdoc14, new CheckBox[] { tipodoc1, tipodoc2, tipodoc3, tipodoc4 });

        }

        public override void actualizar(object referencia, bibliotecaObservador.EventoActualizacion e)
        {
            int numConjunto = (int)referencia;
            if (numConjunto == conjuntoBase.CONJTIPOSPERFIL)
            {
                cargarDatos();
            }
        }

        private void cargarDatos()
        {
            try
            {
                datosActuales = cp.ctrlTipoPerfil.obtenerTiposPerfil();
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }
            llenarListaTiposPerfil(datosActuales);
        }

        /// <summary>
        /// en DGV agrega los nombres de las columnas que va a presentar este 
        /// componente.
        /// </summary>
        private void setColumnas()
        {
            dgv_BusquedaPerfiles.Columns.Clear();
            dgv_BusquedaPerfiles.Columns.Add("columna1", "Identificación");
            dgv_BusquedaPerfiles.Columns.Add("columna2", "Nombre");
        }

        /// <summary>
        /// recibe una lista de tipos de perfil para presentarlos en el DGV
        /// </summary>
        /// <param name="tipoPerfiles"></param>
        private void llenarListaTiposPerfil(LinkedList<tipoPerfil> tipoPerfiles)
        {
            setColumnas();
            if (tipoPerfiles != null)
            {
                foreach (tipoPerfil act in tipoPerfiles)
                {
                    dgv_BusquedaPerfiles.Rows.Add(act.codTipoPerfil, act.nombre);
                }
            }
            
        }

        /// <summary>
        /// Recibe un tipo perfil y escribe los datos en la ventana,
        /// ya sea el nombre en el campo de texto y los permisos en el árbol
        /// </summary>
        /// <param name="tipo"></param>
        private void escribirTipoPerfil(tipoPerfil tipo)
        {
            if (tipo != null)
            {
                txb_NombrePerfil.Text = tipo.nombre;
                arbol.ingresarPermisos(tipo.permisosPredeterminados);
            }
            else
            {
                txb_NombrePerfil.Text = "";
                arbol.vaciarCampos();
            }
        }

        #endregion

        #region "captura"

        /// <summary>
        /// captura los datos de los campos de las ventanas y crea una clase tipo perfil con los datos
        /// de la ventana. Primero valida que estén correctos.
        /// </summary>
        /// <returns></returns>
        private tipoPerfil capturaCampos()
        {
            string permisos = capturaPermisos();
            string nombre = capturaNombre();
            return new tipoPerfil(null, nombre, permisos);
        }

        /// <summary>
        /// obtiene el nombre del campo de texto txt_nombrePerfil
        /// </summary>
        /// <returns></returns>
        private string capturaNombre()
        {
            return txb_NombrePerfil.Text;
        }

        /// <summary>
        /// obtiene la lista (un string de 0 y 1) del árbol 
        /// </summary>
        /// <returns></returns>
        private string capturaPermisos()
        {
            string permisos = arbol.leerPermisos();
            return permisos;
        }

        /// <summary>
        /// Devuelve un tipoPerfil seleccionado del DGV
        /// </summary>
        /// <returns></returns>
        private tipoPerfil capturaSeleccion()
        {
            tipoPerfil nuevo = null;
            try
            {
                dgv_BusquedaPerfiles.Rows[dgv_BusquedaPerfiles.SelectedCells[0].RowIndex].Selected = true;
                String codigo = dgv_BusquedaPerfiles.SelectedRows[0].Cells[0].Value.ToString();
                if (codigo != null)
                {
                    nuevo = getTipoPerfil(codigo);
                }
            }
            catch
            {

            }
            return nuevo;
        }

        /// <summary>
        /// Devuelve el tipoPerfil de acuerdo con el código, lo busca entre datosActuales (los que se listan en el DGV)
        /// </summary>
        /// <param name="codigo"></param>
        /// <returns></returns>
        private tipoPerfil getTipoPerfil(string codigo)
        {
            foreach (tipoPerfil actual in datosActuales)
            {
                if (actual.codTipoPerfil == codigo)
                {
                    return actual;
                }
            }
            return null;
        }

        #endregion

        #region "validación"

        /// <summary>
        /// veririfa que todos los campos para agregar contenga información correcta
        /// </summary>
        /// <returns></returns>
        private bool camposValidosAgregar()
        {
            tipoPerfil nuevo = capturaCampos();
            try
            {
                return cp.ctrlTipoPerfil.camposAgregarValidos(nuevo.nombre, nuevo.permisosPredeterminados);
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
                return false;
            }
        }
            
        #endregion

        #region "acciones"

        /// <summary>
        /// toma los datos de la ventana y los envía a la clase de control para que cree un nuevo tipo de perfil
        /// </summary>
        private void agregarNuevo()
        {
            tipoPerfil nuevo = capturaCampos();
            if (camposValidosAgregar() /*&& cp.usuarioActual().puede(acciones.TIPERF_AGREGAR)*/ && nuevo != null)
            {
                try
                {
                    cp.ctrlTipoPerfil.crearTipoPerfil(nuevo.nombre, nuevo.permisosPredeterminados);
                    mostrarInfo("Agregado correctamente");
                    estado.agregar();
                    actualizaControles();
                }
                catch (Exception e)
                {
                    ventanaError(e.Message + "\nNo se ha podido agregar el nuevo Tipo de Perfil.");
                }
            }
        }

        private void eliminarSelected()
        {
            try
            {
                tipoPerfil editando = capturaSeleccion();
                if ((estado.EDITANDO() && perfilActual != null))
                {
                    cp.ctrlTipoPerfil.eliminarTipoPerfil(perfilActual);
                    estado.consultar();
                    actualizaControles();
                }
                else if (estado.CONSULTANDO() && editando != null)
                {
                    cp.ctrlTipoPerfil.eliminarTipoPerfil(editando);
                    estado.consultar();
                    actualizaControles();
                }
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }

        }

        private void modificarSelected()
        {

            tipoPerfil modificar = capturaCampos();
            if (estado.EDITANDO() && modificar != null)
            {
                modificar.codTipoPerfil = capturaSeleccion().codTipoPerfil;
                try
                {
                    cp.ctrlTipoPerfil.modificarTipoPerfil(modificar);
                    mostrarInfo("Tipo Perfil agregado con éxito");
                    AmodoConsulta();
                }

                catch (Exception e)
                {
                    mostrarInfo(e.Message);
                }  
            }
        }

        private void AmodoConsulta()
        {
            if (estado.AGREGANDO() || estado.EDITANDO())
            {
                estado.consultar();
                actualizaControles();
            }
        }

        private void AmodoEdicion()
        {
            perfilActual = capturaSeleccion();
            if (perfilActual != null)
            {
                estado.editar();
                actualizaControles();
            }
        }

        #endregion

        #region "eventos"

        private void txb_NombrePerfil_TextChanged(object sender, EventArgs e)
        {
            //borrarError(txb_NombrePerfil);
            //lbl_mensajes.Text = string.Empty;
        }

        private void txb_busqueda_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode.Equals(Keys.Enter))
            {
                if (txb_busqueda.Text.Equals(string.Empty))
                {
                    if (modoB)
                    {
                        modoB = false;
                        finalizarBusqueda();
                    }
                }
                else
                {
                    modoB = true;
                    string[] v = new string[] { "columna2" };
                    if (iniciarBusqueda(txb_busqueda.Text, v).Equals(0))
                    {
                        mostrarInfo("La búsqueda no generó ningún resultado.");
                        modoB = false;
                        finalizarBusqueda();
                    }
                }
            }
        }

        private void txb_busqueda_TextChanged(object sender, EventArgs e)
        {
            lbl_mensajes.Text = string.Empty;
        }

        /// <summary>
        /// Envía un mensaje de error en el label de la ventana de estado, este mensaje va de acuerdo
        /// con el número de error.
        /// </summary>
        /// <param name="errores"></param>
        private void enviarInvalidadcion(int[] errores)
        {
            //lbl_mensajes.Text = "Errores en los campos del Tipo de Perfil.";
        }

        public override void hacerVisible(object[] arg)
        {
            base.hacerVisible(arg);
            if (arg != null)
            {
                perfilActual = (tipoPerfil)arg[0];
            }
            else
            {
                cargarDatos();
                AmodoConsulta();
            }
        }

        private void dgv_BusquedaPerfiles_SelectionChanged(object sender, EventArgs e)
        {
            if (estado.CONSULTANDO())
            {
                perfilActual = capturaSeleccion();
                escribirTipoPerfil(perfilActual);
            }
            actualizaControles();
        }

        #endregion

        #region "controles"

        /// <summary>
        /// actualiza los botones de acuerdo con el estado en el que se encuentre
        /// la ventana. Básicamente maneja enable true or false
        /// </summary>
        private void actualizaBotones()
        {
            if (estado.AGREGANDO())
            {
                btn_Nuevo.Enabled = false;
                btn_eliminar.Enabled = false;
                btn_guardar.Enabled = true;
                btn_editar.Enabled = false;
                btn_cancelar.Enabled = true;
            }
            else if (estado.EDITANDO())
            {
                btn_Nuevo.Enabled = false;
                btn_eliminar.Enabled = cp.usuarioActualPuede(acciones.TIPERF_ELIMINAR);
                btn_guardar.Enabled = true;
                btn_editar.Enabled = false;
                btn_cancelar.Enabled = true;
            }
            else if (estado.CONSULTANDO())
            {
                btn_Nuevo.Enabled = cp.usuarioActualPuede(acciones.TIPERF_AGREGAR);
                btn_eliminar.Enabled = perfilActual != null && cp.usuarioActualPuede(acciones.TIPERF_ELIMINAR);
                btn_guardar.Enabled = false;
                btn_editar.Enabled = perfilActual != null && cp.usuarioActualPuede(acciones.TIPERF_MODIFICAR);
                btn_cancelar.Enabled = false;
            }
        }

        /// <summary>
        /// de acuerdo con el estado en el que se encuentre la ventana, cambia los estados
        /// de los campos de texto así como los del árbol para el uso de la ventana
        /// </summary>
        private void actualizaCampos()
        {
            borrarError(txb_NombrePerfil);
            lbl_mensajes.Text = "";

            if (estado.AGREGANDO())
            {
                txb_NombrePerfil.Enabled = true;
                txb_NombrePerfil.Text = "";
                arbol.Activar();
                limpiarCamposArbol();
            }
            else if (estado.EDITANDO())
            {
                txb_NombrePerfil.Enabled = true;
                arbol.Activar();
            }
            else if (estado.CONSULTANDO())
            {
                txb_NombrePerfil.Enabled = false;
                arbol.desActivar();
                actualizarArbolConsulta();
            }
        }

        /// <summary>
        /// aplica solo si se está en modo de consulta y lo que hace es verificar si hay algún
        /// tipo perfil del DGV seleccionado y en caso de ser, agrega los permisos en el árbol
        /// </summary>
        private void actualizarArbolConsulta()
        {
            
        }

        /// <summary>
        /// Deja las casillas del árbol deschekeadas
        /// </summary>
        private void limpiarCamposArbol()
        {
            arbol.vaciarCampos();
        }

        /// <summary>
        /// actualiza todos los controles de la ventana: campos y botones, de acuerdo con el estado
        /// en el que se encuentra
        /// </summary>
        private void actualizaControles()
        {
            actualizaActual();
            actualizaBotones();
            actualizaCampos();
        }

        /// <summary>
        /// actualiza el atributo perfil actual de acuerdo con la selección hecha en el DGV
        /// </summary>
        private void actualizaActual()
        {
            perfilActual = capturaSeleccion();
            escribirTipoPerfil(perfilActual);   
        }

        #endregion
            
        #region "botones"

        private void btn_guardar_Click(object sender, EventArgs e)
        {
            if (txb_NombrePerfil.Text.Equals(string.Empty))
            {
                setError(txb_NombrePerfil, "Ingrese un nombre para el Tipo de Perfil.");
            }
            else
            {
                borrarError(txb_NombrePerfil);
            }

            if(erp_error.GetError(txb_NombrePerfil).Equals(string.Empty))
            {
                if (estado.AGREGANDO())
                {
                    agregarNuevo();
                }
                else if (estado.EDITANDO())
                {
                    modificarSelected();
                }
            }
        }
        
        private void btn_Nuevo_Click(object sender, EventArgs e)
        {
            estado.agregar();
            actualizaControles();
        }

        private void btn_cancelar_Click(object sender, EventArgs e)
        {
            bool modoConsulta = true;
            if (estado.EDITANDO())
            {
                modoConsulta = confirmarOperacion("No se han guardado los cambios, se perderán los cambios si continúa");
            }
            else if (estado.AGREGANDO())
            {
                modoConsulta = confirmarOperacion("No se ha agregado el nuevo Tipo de Perfil y se perderán los cambios\n si continúa");
            }
            if (modoConsulta)
            {
                AmodoConsulta();
            }
            actualizaControles();
        }

        private void btn_editar_Click(object sender, EventArgs e)
        {
            AmodoEdicion();            
        }

        private void btn_eliminar_Click(object sender, EventArgs e)
        {
            tipoPerfil edit=capturaSeleccion();
            if (estado.EDITANDO() || edit != null)
            {
                if (confirmarOperacion("Se eliminará el tipo perfil " + edit.nombre + " de la base de datos"))
                {
                    eliminarSelected();
                }
            }
        }

        //private void btn_guardar_Click(object sender, EventArgs e)
        //{
        //    if (estado.AGREGANDO())
        //    {
        //        agregarNuevo();
        //    }
        //    else if (estado.EDITANDO())
        //    {
        //        modificarSelected();
        //    }
        //}

        //private void btn_Nuevo_Click(object sender, EventArgs e)
        //{
        //    estado.agregar();
        //    actualizaControles();
        //}

        //private void btn_cancelar_Click(object sender, EventArgs e)
        //{
        //    bool modoConsulta = true;
        //    if (estado.EDITANDO())
        //    {
        //        modoConsulta = confirmarOperacion("No se han guardado los cambios, se perderán los cambios si continúa");
        //    }
        //    else if (estado.AGREGANDO())
        //    {
        //        modoConsulta = confirmarOperacion("No se ha agregado el nuevo Tipo de Perfil y se perderán los cambios\n si continúa");
        //    }
        //    if (modoConsulta)
        //    {
        //        AmodoConsulta();
        //    }
        //    actualizaControles();
        //}

        //private void btn_editar_Click(object sender, EventArgs e)
        //{
        //    AmodoEdicion();
        //}

        //private void btn_eliminar_Click(object sender, EventArgs e)
        //{
        //    tipoPerfil edit = capturaSeleccion();
        //    if (estado.EDITANDO() || edit != null)
        //    {
        //        if (confirmarOperacion("Se eliminará el tipo perfil " + edit.nombre + " de la base de datos"))
        //        {
        //            eliminarSelected();
        //        }

        //    }
        //}

        #endregion

        #region "atributos"

        tipoPerfil perfilActual;
        manejaArbol arbol;
        LinkedList<tipoPerfil> datosActuales;

        #endregion
    }
}
